C or Pascal?
Volume: 8
Number: 5
Column Tag: Getting Started
Which is the best language?
By Dave Mark, MacTutor Regular Contributing Author
If my writing seems a little jumpy this month, there’s a good reason for it. I’m
thrilled, pleased, and proud to announce the birth of my first child, Daniel Justin, on
July 27th, 1992 at 5:39 pm. While I could easily write an entire column describing
Daniel’s birthday, suffice it to say that things went relatively smoothly, and we are all
doing fine (and no, Dad, the boy doesn’t have a job yet!).
C and Pascal
Recently, we’ve been getting a lot of mail concerning programming in C vs.
programming in Pascal. Some folks want to know which language is better for
Macintosh programming. Others want some help translating C examples into Pascal and
Pascal examples into C. So far, this column has leaned pretty heavily in the C direction.
In this month’s column, I’ll try to give Pascal equal time.
C or Pascal: What’s the Best Language?
C and Pascal are both procedural, as opposed to object, programming languages.
Pascal is a rigidly formal language, and is said to be strongly typed. C is an informal
language, and is very loosely typed. While Pascal forces you to follow a very specific,
rigidly defined programming style, C offers more notational flexibility.
For example, consider this snippet of C code:
/* 1 */
void main()
{
int age, weight;
for ( age=0,weight=0; age<=20; age++,weight++ )
{
•
•
•
}
}
This for loop initializes two variables, sets the end condition, and increments
both variables each time through the loop (the three dots represent the inner workings
of the loop). Notice how compact this code is.
To emphasize this point, check out the Pascal version of the same loop:
{2}
program MyProgram;
var
age, weight: INTEGER;
begin
weight := 0;
for age := 0 to 20 do
begin
•
•
•
weight := weight + 1;
end;
end.
Beginners may find the Pascal code easier to read than the C code. The Pascal
example is very straight-forward. Each statement consists of a single expression and
the flow is very simple.
The C example, on the other hand, is more complex. Lots of action is crammed
into a single line of code. One advantage to this approach is that by allowing several
variables to be initialized or incremented at the same time, the structure of the loop is
more natural. In the Pascal loop, weight is initialized explicitly, while age is initialized
in the for statement. In the C example, both variables are modified in the same breath,
more closely matching the intent of the loop.
Pascal is more straight-forward, C is more complex. Now the question is, which
of these two languages is better?
The answer to this question depends on your point of view. Some folks claim that
Pascal is a superior language because its straight-forwardness makes it somewhat
easier to learn than C. Is this your first programming language? If so, Pascal might be
the choice for you.
The other side of the coin is C’s power. While Pascal is a safe, dependable Volvo,
C is a turbo-charged Porsche, both powerful and dangerous. If you pick C as your
language, you’ll be forced to develop a carefully considered coding style. Pascal is a
much more forgiving language, but C will really let you fly!
The Support Factor
Whether you are a beginner or an old-timer, you’d probably do just fine no
matter which of the two languages you pick. If you need a little push in one direction or
another, consider the support factor.
Learning a new language can be pretty tough. The right support can make a huge
difference. For example, if your best friend is a C guru, you might choose C over Pascal
(that is, if your buddy won’t mind your harassing him or her with questions all the
time). If you have access to a Pascal course at your school, Pascal might be your best
bet. Once you learn one of these languages, it’s pretty easy to come up to speed on the
other one.
One place you can always turn to for support is your local technical bookstore.
Books are usually a pretty good investment, and there are lots of good C and Pascal titles
available.
All Things Being Equal
If none of this reasoning has swayed you in one direction or another, consider
this argument for C over Pascal. There is a strong movement in programming circles
towards object programming. This movement is likely to get a lot stronger in the
coming years. Apple is doing most of their development in C++, an extremely popular
object programming language that happens to be a superset of C.
Pascal also has a related object programming language, Object Pascal. Most
likely, in coming years you’ll be able to develop complete Macintosh applications in
both Object Pascal and C++. So why am I leaning towards C and C++? Support, support,
support...
Here’s why: Go down to your local Software Etc. (or whatever technical
bookstore you’ve got in your neck of the woods) and count all the Pascal/Object Pascal
books. Next count all the C/C++ books. Chances are, the C and C++ books will
outnumber the Pascal/Object Pascal books by at least five to one. This should tell you
something.
C and C++ have skyrocketed in popularity in recent years and interest in Pascal
and Object Pascal has cooled off. All things being equal, I’d choose C over Pascal. Nothing
against Pascal, you understand. It’s just a question of support. My feeling is, over the
coming years, I’m going to be able to find C/C++ support a lot more readily than
Pascal/Object Pascal support.
Navigating Between C and Pascal
Whether you select C or Pascal, you’ll want to be able to navigate between the
two languages. One big reason for this is the proliferation of C and Pascal sample code.
If you are trying to solve a specific Macintosh interface problem, there’s no substitute
for an example. Murphy’s Law being what it is, if you are programming in one
language, the only example you’ll be able to turn up will be in the other language.
C programmers have another reason for learning to read Pascal code. Most of the
original Macintosh operating system was written in Pascal. Because of this, most of the
examples in Inside Macintosh and in the Macintosh Technical Notes are in Pascal. In
addition, the Toolbox routines were designed to take advantage of the Pascal parameter
passing mechanism.
The remainder of this column will explore some of the differences between C and
Pascal and will help C programmers call Toolbox routines designed for Pascal
programmers.
Calling the Toolbox From C
Pull out your copy of Inside Macintosh, Volume I, and turn to page 283. There
you’ll find the calling sequence for the Toolbox routine GetNewWindow():
{3}
FUNCTION GetNewWindow( windowID: INTEGER;
wStorage: Ptr;
behind: WindowPtr ): WindowPtr;
The first word in this calling sequence tells you whether the routine being
described returns a value or not. In the case of a FUNCTION, the routine returns a value
of the type listed at the end of the calling sequence. The calling sequence above tells you
that GetNewWindow() returns a WindowPtr.
If the routine is declared as a PROCEDURE, it doesn’t return a value and is
analagous to a C routine declared as a void.
Translating Pascal Types to C Types
Once you’ve figured out whether the Toolbox routine under consideration returns
a value or not, you’ll need to figure out the C data types that correspond to each of the
routine’s parameters. This process is actually pretty easy. For starters, take a look at
this table:
Pascal Data Type THINK C Equivalent
INTEGER short
LONGINT long
CHAR short
BOOLEAN Boolean
A Toolbox parameter declared as an INTEGER corresponds to the THINK C type
short. Both of these types are two bytes in length. The Pascal type LONGINT corresponds
to the THINK C type long. The Pascal type CHAR corresponds to the THINK C type short,
and the Pascal type BOOLEAN corresponds to the THINK C type Boolean. The Pascal type
Ptr corresponds to a C pointer. In the Macintosh world, both pointers and Ptrs are four
bytes in length. In C, a pointer is declared using the * operator.
In addition to these basic Pascal types, you’ll frequently encounter types specific
to the Toolbox. For example, the Window Manager defines the type WindowPtr. When
you run into one of these Toolbox types, just use them as is. Typically, the Toolbox
types are named using the same conventions as the Toolbox routines. The name is
divided into a series of words. The first letter of each word is an upper-case letter
while the remainder of each word is spelled with lower-case letters. This gives you
Toolbox types such as WindowPtr, Rect, and GrafPort.
Let’s go back to the GetNewWindow() call presented earlier:
{4}
FUNCTION GetNewWindow( windowID: INTEGER;
wStorage: Ptr;
behind: WindowPtr ): WindowPtr;
To call this routine from C, you'll want to pass a short, a pointer, and a
WindowPtr as parameters. Finally, you'll receive the result in a variable of type
WindowPtr:
/* 5 */
#define kBaseResID 128
#define kMoveToFront (WindowPtr)-1L
WindowPtr window;
window = GetNewWindow( kBaseResID, nil, kMoveToFront );
Notice that we passed constants as parameters. As long as the values are of the
proper type, this works just fine.
Remember, C is a case-sensitive language and Pascal is not. In Pascal, you can
get away with spelling horrors like WINDowptr and WiNdOwPtR. In C, however, you’d
best get it right: WindowPtr.
C and Pascal Strings
In C, text strings are represented by a series of bytes terminated by a null byte,
a byte with a value of 0. In Pascal, however, text strings are stored in a variable of
type Str255. The first byte of a Str255 is known as a length byte and indicates the
length of the text string. The string itself is imbedded in the bytes that follow the length
byte. Since the length byte can hold values from 0 to 255, a Pascal text string can be
anywhere from 0 to 255 bytes long. C strings are limited only by available memory.
For example, this figure shows a Pascal string containing the text string “Hello,
World!”:
Figure 1
The first byte has a value of 13, describing the length of the text string. This
figure, on the other hand, shows the same string represented as a C string:
Figure 2
Notice that the string is terminated by a byte with a value of zero.
When a Toolbox routine makes use of a Str255, you need to pass it a string in the
Pascal format. For example, here’s the calling sequence for the Toolbox routine
DrawString():
{6}
PROCEDURE DrawString( s: Str255 );
You must call DrawString() with a proper Pascal string. THINK C helps you in
this regard by offering a special escape sequence you can use to declare a Pascal string
literal in C. If THINK C encounters the characters \p at the very beginning of a string
literal, the string is stored as a Pascal Str255. For example, this call to DrawString()
works like a charm:
/* 7 */
DrawString( "\pHello, World!" );
You might also find it useful to use \p in a #define:
/* 8 */
#define kMyString "\pHello, World!
DrawString( kMyString );
This approach works just as well.
THINK C also provides the routines CToPStr() and PToCStr() to translate a C
string to Pascal and a Pascal string to C. Note that these routines are not part of the
Macintosh Toolbox. They are provided as a service by THINK C.
When to Use the &
Another important issue for C programmers concerns the & operator and its use
in parameter passing. Pascal parameters are normally passed by reference. This means
that you can pass an INTEGER into a routine and, if the routine modifies the INTEGER,
the changed value goes back to the calling routine.
C normally passes parameters by value. In C, if you pass a short to a routine, and
the routine modifies the short, the modification only affects the local copy of the short
and not the calling routine’s copy. To pass a parameter by reference in C, you’ll
typically pass a pointer to the variable:
/* 9 */
MyRoutine( &myVar );
There’s more to parameter passing than just sticking an & in front of any
parameter you want to pass by reference. Here’s a set of four rules you should use to
decide when the & is appropriate when making Toolbox calls. These rules can be found
in Volume I of the Mac C Primer:
1) If a parameter is declared as a VAR parameter in the Pascal calling
sequence, precede it by an &. Here’s the Pascal calling sequence for GetFNum():
{10}
PROCEDURE GetFNum( fontName: Str255;
VAR theNum: INTEGER );
Here’s a C code fragment that calls GetFNum():
/* 11 */
short myFontNumber;
GetFNum( "\pGeneva", &myFontNumber );
2) If the parameter is bigger than 4 bytes (as is the case with most Pascal
and C data structures), precede it by an & whether or not it is declared as a VAR
parameter. Here’s the Pascal calling sequence for UnionRect():
{12}
PROCEDURE UnionRect( src1, src2: Rect;
VAR dstRect: Rect );
Here’s a C fragment that calls UnionRect():
/* 13 */
Rect src1, src2, dstRect;
•
• /* assign values to src1 and src2 */
•
UnionRect( &src1, &src2, &dstRect );
3) If the parameter is 4 bytes or smaller and is not declared as a VAR
parameter, pass it without the &. This rule applies even if the parameter is a struct.
This is the Pascal declaration of the routine PtToAngle():
{14}
PROCEDURE PtToAngle( r: Rect;
pt: Point;
VAR angle: INTEGER );
Here’s a C fragment that calls PtToAngle():
/* 15 */
Rect r;
Point pt;
short angle;
•
• /* assign values to r and pt */
•
PtToAngle( &r, pt, &angle );
Notice that pt was passed without a leading &. This is because Points are
only 4 bytes in size. Most of the predefined Mac types are larger than 4 bytes in size.
Point is one of the few exceptions.
4) If the parameter is a Str255, do not use an &, even if the parameter is
declared as a VAR. This is the Pascal declaration of the routine GetFontName():
/* 16 */
PROCEDURE GetFontName( fontNum: INTEGER;
VAR theName: Str255 );
Here is an example of a Pascal string used in a Toolbox call:
{17}
Short fontNum;
Str255 fontName;
fontNum = 4;
GetFontName( fontNum, fontName );
Note that fontName was passed without a leading &.
Last Month’s Program In Pascal
Last month we worked through a program called PICTWindow. Since this column
focused on Pascal, I thought you might like to see a Pascal version of PICTWindow. Here
it is...
Create a new folder called PICTWindow. Follow the directions in last month’s
column to create the resource file called PICTWindow.π.rsrc and copy the file into the
PICTWindow folder.
Next, launch THINK Pascal and create a new project in the PICTWindow folder.
Select Run Options... from the Run menu and click on the Use Resource File: checkbox.
When prompted, select the PICTWindow.π.rsrc file in the PICTWindow folder, then click
the OK button.
Next, select New from the File menu to create a new source code window. Type in
this source code:
program PICTWindow;
const
kBaseResID = 128;
{----------------> WindowInit <--}
procedure WindowInit;
var
window: WindowPtr;
begin
window := GetNewWindow(kBaseResID, nil, WindowPtr(-1));
if window = nil then
begin
SysBeep(10);
ExitToShell;
end;
ShowWindow( window);
SetPort( window);
end;
{----------------> DrawMyPicture <--}
procedure DrawMyPicture;
var
pictureRect: Rect;
picture: PicHandle;
begin
picture := GetPicture(kBaseResID);
if picture = nil then
begin
SysBeep(10);
ExitToShell;
end;
pictureRect := picture^^.picFrame;
OffsetRect(pictureRect, -pictureRect.left, -pictureRect.top);
DrawPicture(picture, pictureRect);
FrameRect(pictureRect);
end;
{----------------> PICTWindow <--}
begin
WindowInit;
DrawMyPicture;
while not Button do
;
end.
Finally, save the source code as PICTWindow.p and add the file to the project.
Select Go from the Run menu to run the program. Enjoy!
Next Month
Next month we’ll return to the topic of resources. Till then, it’s back to late
nights and diaper changing. Coming, Daniel...